package com.tfswx.jcyw.sqlmodel.api.executor;

import com.tfswx.jcyw.sqlmodel.api.OperatorChain;
import com.tfswx.jcyw.sqlmodel.api.bean.ExecuteInputDTO;
import com.tfswx.jcyw.sqlmodel.api.bean.Node;
import com.tfswx.jcyw.sqlmodel.api.bean.table.Select;
import com.tfswx.jcyw.sqlmodel.api.function.FunctionUtil;
import com.tfswx.jcyw.sqlmodel.api.function.RuntimeFuntion;
import lombok.Data;

import java.util.*;
import java.util.stream.Collectors;

/**
 * @author 张述江
 * @date 2023/9/7
 */
@Data
public final class SqlModelExecutor {

    private Executor executor;
    private OperatorChain operatorChain;

    public void execute(ExecuteInputDTO inputDTO) {
        List<RuntimeFuntion> functionList = operatorChain.getFunctionList();
        if (functionList != null) {
            FunctionUtil.addFunctions(functionList);
        }

        List<Node> nodeList = inputDTO.getNodeList();
        if (nodeList == null || nodeList.isEmpty()) {
            throw new RuntimeException("没有任何节点");
        }
        // 整理nodeList
        Map<String, Node> nodeMap = new HashMap<>();
        for (Node node : nodeList) {
            nodeMap.put(node.getJdbh(), node);
        }
        // 清理无用的父级节点
        for (Node node : nodeList) {
            List<String> pidList = node.getFjdbhList();
            if (pidList == null) {
                pidList = new ArrayList<>();
            }
            node.setLevel(0);
            List<String> tempList = new ArrayList<>();
            for (String pid : pidList) {
                if (nodeMap.containsKey(pid)) {
                    tempList.add(pid);
                }
            }
            node.setFjdbhList(tempList);
        }
        // 整理节点等级
        refreshLevel(nodeMap);
        nodeList.sort(Comparator.comparingInt(Node::getLevel));


        Map<Integer, List<Node>> levelNodeMap = nodeList.stream().collect(Collectors.groupingBy(Node::getLevel));

        // 待执行等级
        Set<Integer> levelSet = levelNodeMap.keySet();

        // 等级排序
        List<Integer> levelList = levelSet.stream().sorted().collect(Collectors.toList());

        // 开始执行
        for (Integer level : levelList) {
            for (Node node : levelNodeMap.get(level)) {
                // 获取父级的执行结果
                List<Select> pResultList = node.getFjdbhList().stream().map(x -> Select.fromJson(executor.getResult(x))).collect(Collectors.toList());
                // 执行节点
                Select result = operatorChain.execute(node, pResultList);
                System.out.println("节点" + node.getJdbh() + "运行结果：" + result);
                executor.saveResult(node.getJdbh(), Select.toJson(result));
                if (Boolean.TRUE.equals(node.getLeaf())) {
                    // 打印结果
                    executor.complete(result);
                }
            }
        }
    }

    private void refreshLevel(Map<String, Node> nodeMap) {
        // 组装成树形结构
        Map<String, List<Node>> childrenMap = new HashMap<>();

        List<Node> root = new ArrayList<>();

        nodeMap.forEach((id, node) -> {
            List<String> pidList = node.getFjdbhList();
            if (pidList == null || pidList.isEmpty()) {
                root.add(node);
                return;
            }
            for (String pid : pidList) {
                List<Node> children = childrenMap.computeIfAbsent(pid, k -> new ArrayList<>());
                children.add(node);
            }
        });

        setLevel(root, childrenMap, 0);

    }

    private void setLevel(List<Node> nodeList, Map<String, List<Node>> childrenMap, int level) {
        for (Node node : nodeList) {
            // 设置自身节点的level
            node.setLevel(Math.max(node.getLevel(), level));
            // 设置子级节点的level
            List<Node> nodeList1 = childrenMap.get(node.getJdbh());
            if (nodeList1 != null) {
                setLevel(nodeList1, childrenMap, level + 1);
            } else {
                node.setLeaf(true);
            }
        }
    }
}
